#ifndef ZZ_LOCK_H
#define ZZ_LOCK_H

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
#include <pthread.h>
#include "Socket2.h"
#include <string.h>

using namespace std;

#define MAX_READ_LEN            1024
#define METHOD_OPEN_BOX         0x2B01
#define METHOD_BOX_OPENED       0x2C01
#define METHOD_INSPECT          0x3B01
#define METHOD_INSPECTED        0x3C01
#define PKT_HEADER              0xA5
#define PKT_END                 0x5A
#define PKT_HEADER_LEN          8

enum LockStatus {
    LOCK_OK = 0,
    LOCK_FAIL = 0x80
};

#pragma pack(1)

struct LOCK_PKT_HEADER {
    unsigned char header;
    unsigned short len;
    unsigned short cabinet_id;
    unsigned char box_id;
    unsigned short cmd;
};

struct LOCK_PKT_HEADER2 {
    unsigned char header;
    unsigned short len;
    unsigned short cabinet_id;
    unsigned char box_id;
    unsigned short cmd;
    unsigned char result;
};
#pragma pack()

class Lock {
public:
    Lock();
    ~Lock();

    int connect(const char* ip, short port, unsigned char cabinetId);

    int disconnect();

    int open(unsigned char port);

    int stop_inspect();

    int start_inspect();

    int get_opened(unsigned char *opened, int &len);

    jobject thiz;
    JavaVM* jvm;

protected:
    Socket2 socket2;
    char ip[20];

    unsigned char opened[60];

    unsigned char cabinetId;

private:
    /**
     * 读取网络数据线程
     */
    bool read_thread_flag;
    pthread_t read_thread;
    static void *ReadThreadProc(void *args);

    /**
    * 巡检线程
    */
    static void *InspectThreadProc(void *args);

    bool inspect_thread_flag;
    pthread_t inspect_thread;

    sem_t cmd_semaphore;
    struct timespec sem_add_ms(int ms) {
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        long secs = ms / 1000;
        ms = ms % 1000;

        long add = 0;
        long ns = ms * 1000 * 1000 + ts.tv_nsec;
        add = ns / (1000 * 1000 * 1000);
        ts.tv_sec += (add + secs);
        ts.tv_nsec = ns % (1000 * 1000 * 1000);
        return ts;
    }

    int write_cmd(unsigned short cmd, unsigned short cabinet_id, unsigned char box_id);
};

#endif //ZZ_LOCK_H
